//============================================================================
// Name        : Index.cpp
// Author      : lucmir@dcc.ufmg.br
// Description :
//============================================================================

#include "Index.h"


Index::Index(Lexon *lexon) :
	lexon(lexon) {
	this->pos = 0;
	this->lastTermId = 0;
	this->tf = 1;
	this->initPos = 0;
	this->buffer = new unsigned int[BUFFER_SIZE + 2];
	this->bufferPos = 0;
}

Index::~Index() {
}

bool Index::openToWrite(std::string fileName) {
	this->ofs.open(fileName.c_str(), std::ios::out | std::ios_base::binary);
	if(!this->isOpenToWrite()) {
		std::cout << "\nERRO: Não foi possível abrir o arquivo: \"" << fileName << "\"\n\n";
		return false;
	}
	return true;
}

bool Index::isOpenToWrite() {
	if(this->ofs != NULL && this->ofs.is_open()) {
		return true;
	}
	return false;
}

bool Index::isOpenToRead() {
	if(this->ifs != NULL && this->ifs.is_open()) {
		return true;
	}
	return false;
}

void Index::closeToWrite() {
	if(this->ofs.is_open()) {
		// flush the last term info to the vocabulary
		this->lexon->setPosition(this->lastTermId, this->initPos);
		// flush buffer
		if(this->bufferPos > 0) {
			this->flushBuffer();
		}
		this->ofs.close();
	}
}

bool Index::openToRead(std::string fileName) {
	this->ifs.open(fileName.c_str(), std::ios::in | std::ios_base::binary);
	return this->isOpenToRead();
}

void Index::closeToRead() {
	if(this->ifs.is_open()) {
		this->ifs.close();
	}
}

void Index::insert(Registry &registry) {
	// Write to index
	if(this->pos != 0 && this->lastTermId != registry.getTermId()) {
		// Update last term position and frequency in vocabulary
		this->lexon->setPosition(this->lastTermId, this->initPos);
		this->initPos = this->pos;
	}
	this->buffer[this->bufferPos++] = registry.getDocId();
	this->buffer[this->bufferPos++] = registry.getFreq();
	this->pos += (2 * UINT_SIZE);
	this->lastTermId = registry.getTermId();
	if(this->bufferPos >= BUFFER_SIZE) {
		this->flushBuffer();
	}
}

void Index::flushBuffer() {
	this->ofs.write((char *)this->buffer, UINT_SIZE * this->bufferPos);
	this->bufferPos = 0;
}

QueryResult *Index::queryTerm(std::string term) {
	std::string line;
	unsigned int tf, position;
	unsigned int resultLen;
	Lexon::VocabularyItem *item;

	if(!this->isOpenToRead()) {
		return NULL;
	}

	item = this->lexon->vocabularyGetItem(term);
	if(item) {
		tf = item->getTf();
		position = item->getPosition();

		resultLen = 2*tf;
		unsigned int *docFreqs = new unsigned int[resultLen];
		this->ifs.seekg(position);
		this->ifs.read( (char *)docFreqs, resultLen * UINT_SIZE );

		QueryResult *qr = new QueryResult(term, tf, docFreqs);
		return qr;
	}
	// Term not found
	return false;
}

unsigned int Index::getPos() {
	return this->pos;
}

Lexon *Index::getLexon() {
	return this->lexon;
}
